//*****************************************************************************
//* Foxit Digital Rights Management Library
//*
//* Foxit Software Inc.
//* Copyright(C) 2005-2010, all rights reserved.
//*
//* The following code is copyrighted and contains proprietary information
//* and trade secrets of Foxit Software Inc.
//*****************************************************************************
/**
 * @addtogroup FDRM
 * @{
 */

/**
 * @file
 * @brief Define operators used in FDRM.
 */

#ifndef _FDRM_OPERATOR
#define _FDRM_OPERATOR

//Classes defined in this header
class CFDRM_Operator;

//*****************************************************************************
//* Operator
//*****************************************************************************
/**
 * @name Operator
 */
/*@{*/

/**
 * @brief Operator data structure
 */
typedef struct _FDRM_OPERATOR
{
	FX_LPCSTR	pbsName;		//operator name
	FX_DWORD	dwOperatorID;	//operator identity
	FX_DWORD	dwKeySize;		//key size in bytes
	FX_DWORD	dwVersion;		//version number
}FDRM_OPERATOR, * FDRM_LPOPERATOR;
typedef FDRM_OPERATOR const * FDRM_LPCOPERATOR;

/**
 * @brief Operator class for FDRM.
 */
class CFDRM_Operator : public CFX_Object
{
public:
	/** @brief	Default constructor. */
	CFDRM_Operator() : m_bsName() , m_dwID(0) , m_dwKeySize(0) , m_dwVersion(0) {}
	/**
	 * @brief	Constructor, constructed by an operator data pointer.
	 * @param[in] pOperator		Points to an operator data pointer.
	 */
	CFDRM_Operator(FDRM_LPCOPERATOR pOperator)
		: m_bsName(pOperator->pbsName)
		, m_dwID(pOperator->dwOperatorID)
		, m_dwKeySize(pOperator->dwKeySize)
		, m_dwVersion(pOperator->dwVersion)
	{
	}
	/** @brief	Copy constructor. */
	CFDRM_Operator(const CFDRM_Operator &op)
		: m_bsName(op.m_bsName)
		, m_dwID(op.m_dwID)
		, m_dwKeySize(op.m_dwKeySize)
		, m_dwVersion(op.m_dwVersion)
	{
	}
	/** Destructor */
	~CFDRM_Operator()
	{
		m_bsName.Empty();
	}

	/** @brief	override assignment operator */
	CFDRM_Operator&		operator = (const CFDRM_Operator &op)
	{
		m_bsName = op.m_bsName;
		m_dwID = op.m_dwID;
		m_dwKeySize = op.m_dwKeySize;
		m_dwVersion = op.m_dwVersion;
		return *this;
	}

	/** @brief	Retrieve the operator name. */
	CFX_ByteStringC		GetName() const {return m_bsName;}
	/** @brief	Retrieve the operator identity code. */
	FX_DWORD			GetID() const {return m_dwID;}
	/** @brief	Retrieve the key size of operator, in bytes. */
	FX_DWORD			GetKeySize() const {return m_dwKeySize;}
	/** @brief	Retrieve the bit count of key. */
	FX_DWORD			GetBitCount() const {return m_dwKeySize << 3;}
	/**
	 * @brief	Calculate an appropriate block size according to the given block size.
	 * @param[in] dwRefSize		referenced block size to calculate the new one.
	 * @return	Return the new block size which must be a multiple value to key size.
	 */
	FX_DWORD			GetBlockSize(FX_DWORD dwRefSize) const {return dwRefSize / m_dwKeySize * m_dwKeySize;}
	/** @brief	Retrieve the version of operator. */
	FX_DWORD			GetVersion() const {return m_dwVersion;}

protected:
	CFX_ByteString	m_bsName;		//operator name
	FX_DWORD		m_dwID;			//operator identity
	FX_DWORD		m_dwKeySize;	//key size in bytes
	FX_DWORD		m_dwVersion;	//version number
};

/** @brief Macro to build a double-word ID, v means a sub version. */
#define FDRM_BSTRID(c1, c2, c3, c4, v) (((FX_DWORD)((c1 - ' ') & 0x3F) << 26) | ((FX_DWORD)((c2 - ' ') & 0x3F) << 20) | ((FX_DWORD)((c3 - ' ') & 0x3F) << 14) | ((FX_DWORD)((c4 - ' ') & 0x3F) << 8) | (v & 0xFF))

/**
 * @brief Macro to declare an operator data.
 * a is formal name of operator;
 * t is unique name of operator;
 * i is identity code of operator;
 * b is bit count of operator;
 * v is the version numer;
 * s is the sub version which is used to distinguish different versions.
 */
#define FDRM_OPERATOR_DEFINE(a, t, i, b, v, s) \
	const FDRM_OPERATOR FDRM_OPERATOR_##a##_##b##_V##s = {"Foxit-" #a "-" #b, i, b >> 3, v};

/**
 * @brief Macro to help declare an object of one operator
 * @code
 *		FDRM_OPERATOR_DECLARE(arc4Op, FDRM_OPERATOR_ARC4_256_V0);
 *		FX_DWORD dwID = arc4Op.GetID();
 * @endcode
 */
#define FDRM_OPERATOR_DECLARE(v, t) \
	CFDRM_Operator v(&t)

/*@}*/

//*****************************************************************************
//* Identities for digest/hash algorithms
//*****************************************************************************
/**
 * @name Identities for digest/hash algorithms
 */
/*@{*/

/** @brief macro ID for 128bits MD5, "Foxit-MD5-128", FDRM_OPERATOR_MD5_128_V0 */
FDRM_OPERATOR_DEFINE(MD5, MD5, FDRM_BSTRID('F', 'M', 'D', '5', 0), 128, 0x20100731, 0)
/** @brief macro ID for 160bits SHA1, "Foxit-SHA1-160", FDRM_OPERATOR_SHA1_160_V0 */
FDRM_OPERATOR_DEFINE(SHA1, SHA1, FDRM_BSTRID('S', 'H', 'A', '1', 0), 160, 0x20100731, 0)
/** @brief macro ID for 256bits SHA2, "Foxit-SHA2-256", FDRM_OPERATOR_SHA2_256_V0 */
FDRM_OPERATOR_DEFINE(SHA2, SHA2, FDRM_BSTRID('S', 'H', 'A', '2', 0), 256, 0x20100731, 0)

/*@}*/

//*****************************************************************************
//* Identities for symmetric crypto algorithms
//*****************************************************************************
/**
 * @name Identities for symmetric crypto algorithms
 */
/*@{*/

/** @brief macro ID for 256bits ARC4, "Foxit-ARC4-256", FDRM_OPERATOR_ARC4_256_V0 */
FDRM_OPERATOR_DEFINE(ARC4, ARC41, FDRM_BSTRID('R', 'C', '4', '1', 0), 256, 0x20100731, 0)
/** @brief macro ID for 512bits ARC4, "Foxit-ARC4-512", FDRM_OPERATOR_ARC4_512_V0 */
FDRM_OPERATOR_DEFINE(ARC4, ARC42, FDRM_BSTRID('R', 'C', '4', '2', 0), 512, 0x20100731, 0)
/** @brief macro ID for 1024bits ARC4, "Foxit-ARC4-1024", FDRM_OPERATOR_ARC4_1024_V0 */
FDRM_OPERATOR_DEFINE(ARC4, ARC43, FDRM_BSTRID('R', 'C', '4', '3', 0), 1024, 0x20100731, 0)
/** @brief macro ID for 2048bits ARC4, "Foxit-ARC4-2048", FDRM_OPERATOR_ARC4_2048_V0 */
FDRM_OPERATOR_DEFINE(ARC4, ARC44, FDRM_BSTRID('R', 'C', '4', '4', 0), 2048, 0x20100731, 0)

/** @brief macro ID for 128bits AES, "Foxit-AES-128", FDRM_OPERATOR_AES_128_V0 */
FDRM_OPERATOR_DEFINE(AES, AES1, FDRM_BSTRID('A', 'E', 'S', '1', 0), 128, 0x20100731, 0)
/** @brief macro ID for 192bits AES, "Foxit-AES-192", FDRM_OPERATOR_AES_192_V0 */
FDRM_OPERATOR_DEFINE(AES, AES2, FDRM_BSTRID('A', 'E', 'S', '2', 0), 192, 0x20100731, 0)
/** @brief macro ID for 256bits AES, "Foxit-AES-256", FDRM_OPERATOR_AES_256_V0 */
FDRM_OPERATOR_DEFINE(AES, AES3, FDRM_BSTRID('A', 'E', 'S', '3', 0), 256, 0x20100731, 0)

/*@}*/

//*****************************************************************************
//* Identities for asymmetric crypto algorithms
//*****************************************************************************
/**
 * @name Identities for asymmetric crypto algorithms
 */
/*@{*/

/** @brief macro ID for 1024bits RSA, "Foxit-RSA-1024", FDRM_OPERATOR_RSA_1024_V0 */
FDRM_OPERATOR_DEFINE(RSA, RSA1, FDRM_BSTRID('R', 'S', 'A', '1', 0), 1024, 0x20100731, 0)
/** @brief macro ID for 2048bits RSA, "Foxit-RSA-2048", FDRM_OPERATOR_RSA_2048_V0 */
FDRM_OPERATOR_DEFINE(RSA, RSA2, FDRM_BSTRID('R', 'S', 'A', '2', 0), 2048, 0x20100731, 0)
/** @brief macro ID for 3072bits RSA, "Foxit-RSA-3072", FDRM_OPERATOR_RSA_3072_V0 */
FDRM_OPERATOR_DEFINE(RSA, RSA3, FDRM_BSTRID('R', 'S', 'A', '3', 0), 3072, 0x20100731, 0)
/** @brief macro ID for 4096bits RSA, "Foxit-RSA-4096", FDRM_OPERATOR_RSA_4096_V0 */
FDRM_OPERATOR_DEFINE(RSA, RSA4, FDRM_BSTRID('R', 'S', 'A', '4', 0), 4096, 0x20100731, 0)
/** @brief macro ID for 1024bits DSA, "Foxit-DSA-1024", FDRM_OPERATOR_DSA_1024_V0 */
FDRM_OPERATOR_DEFINE(DSA, DSA, FDRM_BSTRID('F', 'D', 'S', 'A', 0), 1024, 0x20100731, 0)

/*@}*/

//*****************************************************************************
//* Identities for certificates
//*****************************************************************************
/**
 * @name Identities for certificates
 */
/*@{*/

/** @brief macro ID for 1024bits RSA/DSA certificate, "Foxit-CERT-1024", FDRM_OPERATOR_CERT_1024_V0 */
FDRM_OPERATOR_DEFINE(CERT, CERT, FDRM_BSTRID('C', 'E', 'R', '1', 0), 1024, 0x20100731, 0)

/*@}*/

#endif //_FDRM_OPERATOR

/** @} */
